package com.common.utilities;

import java.io.IOException;
import java.nio.channels.SocketChannel;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.apache.log4j.Logger;

/**
 * User: wattsc5
 * <p/>
 * Date: 2/26/12
 */
public class ReceiveData
{
	private static final Logger logger = Logger.getLogger(ReceiveData.class);

	private String originalData;

	private SocketChannel socketChannel;

	private List<String> arguments;

	/**
	 * Initializes a new instance of a ReceiveData.
	 *
	 * @param data the original data
	 * @param arguments the data as arguments
	 * @param socketChannel the socket that this data came from.
	 * @throws java.io.IOException When the data is not in valid form.
	 */
	private ReceiveData(String data, List<String> arguments, SocketChannel socketChannel)
		throws IOException
	{
		this.originalData = data;
		this.socketChannel = socketChannel;
		this.arguments = arguments;
	}

	private static List<String> splitMultipleData(String originalData)
	{
		List<String> splitData = Arrays.asList(originalData.split("]"));
		List<String> results = new ArrayList<String>();

		// Add the char back on because we need it to validate it later
		for (String data : splitData)
		{
			data += "]";
			results.add(data);
		}

		return results;
	}

	private static String removeUnNeededChars(String dataAsString)
	{
		//NOTE: This assumes there are no spaces allowed in the message.
		dataAsString = dataAsString.replaceAll(" ", "");
		dataAsString = dataAsString.replaceAll("\n", "");
		dataAsString = dataAsString.replaceAll("\r", "");

		return dataAsString;
	}

	private static void checkForValidData(String dataAsString)
		throws IOException
	{
		int dataLength = dataAsString.length();

		if (dataLength == 0)
		{
			throw new IOException("Invalid length");
		}

		if (dataAsString.charAt(0) != '[')
		{
			throw new IOException("Missing '[' char");
		}

		if (dataAsString.charAt(dataLength - 1) != ']')
		{
			throw new IOException("Missing ']' char");
		}

		if (dataAsString.matches("[a-zA-Z0-9]*"))
		{
			throw new IOException("Contains non alpha numeric characters");
		}
	}

	public SocketChannel getSocketChannel()
	{
		return socketChannel;
	}

	public String getOriginalData()
	{
		return this.originalData;
	}

	/**
	 * Gets the first argument in the list.
	 *
	 * @return the first argument in the list.
	 */
	public String getCommandName()
	{
		return this.arguments.get(0);
	}

	/**
	 * Gets an argument from the specified index.
	 *
	 * @param index the index of the argument the caller wants.
	 *
	 * @return the argument at the specified index.
	 */
	public String getArgument(int index)
	{
		return this.arguments.get(index);
	}

	/**
	 * Converts the argument to a string before giving it back to the caller.
	 *
	 * @param index the index of the argument the caller wants.
	 *
	 * @return the argument parsed as an int.
	 */
	public int getArgumentAsInt(int index)
	{
		return Integer.parseInt(this.arguments.get(index));
	}

	public int getArgumentCount()
	{
		return this.arguments.size();
	}

	public static List<ReceiveData> extractDataSets(byte[] data, SocketChannel socketChannel)
		throws IOException
	{
		List<ReceiveData> receiveDataArrayList = new ArrayList<ReceiveData>();

		String originalData = removeUnNeededChars(new String(data));
		List<String> splitData = splitMultipleData(originalData);

		for (String receivedData : splitData)
		{
			checkForValidData(receivedData);

			receivedData = receivedData.substring(1, receivedData.length() - 1);

			List<String> arguments = Arrays.asList(receivedData.split(","));

			receiveDataArrayList.add(new ReceiveData(receivedData, arguments, socketChannel));
		}

		return receiveDataArrayList;
	}

	public String toString()
	{
		return this.originalData;
	}
}
